package registrycenter

import (
	"context"
	"fmt"
	consulApi "github.com/hashicorp/consul/api"
	"wmicro/registry"
)

// ConsulRegisterCenter 实现服务注册/注销
type ConsulRegisterCenter struct {
	client       *consulApi.Client
	clientConfig *consulApi.Config
}

type ConsulRegisterCenterOptions func(o *ConsulRegisterCenter)

func WithConsulRegisterCenterClientConfig(clientConfig *consulApi.Config) ConsulRegisterCenterOptions {
	return func(o *ConsulRegisterCenter) {
		o.clientConfig = clientConfig
	}
}

func NewConsulRegisterCenter(opts ...ConsulRegisterCenterOptions) (registry.IRegistrar, error) {
	r := &ConsulRegisterCenter{
		clientConfig: consulApi.DefaultConfig(),
	}

	for _, o := range opts {
		o(r)
	}

	client, err := consulApi.NewClient(r.clientConfig)
	if err != nil {
		return nil, err
	}

	r.client = client
	return r, err
}

func (r *ConsulRegisterCenter) Register(ctx context.Context, service *registry.ServiceRegisterInfo) error {
	// 1.注册服务信息
	reg := consulApi.AgentServiceRegistration{}
	reg.ID = service.ID
	reg.Name = service.Name
	reg.Address = service.Host
	reg.Port = service.Port
	reg.Tags = []string{fmt.Sprintf("%s:%d", reg.Address, reg.Port)}

	// 2.设置健康检查
	// 创建健康检查
	check := &consulApi.AgentServiceCheck{
		HTTP:                           fmt.Sprintf("http://%s:%d/health", reg.Address, reg.Port), // 健康检查地址，必须设置为 http
		Timeout:                        "2s",                                                      // 超时时间
		Interval:                       "5s",                                                      // 检查间隔
		DeregisterCriticalServiceAfter: "30s",                                                     // 失败后多久移除服务
	}

	// 3.添加检查
	reg.Check = check
	fmt.Println(reg.Check.HTTP)

	// 4.注册服务
	err := r.client.Agent().ServiceRegister(&reg)
	if err != nil {
		return err
	}

	// http://106.13.184.120:8500/ui/dc1/services 服务面板
	// http://127.0.0.1:8500/v1/agent/services	查看注册服务

	return nil
}

func (r *ConsulRegisterCenter) Deregister(ctx context.Context, service *registry.ServiceRegisterInfo) error {
	return r.client.Agent().ServiceDeregister(service.ID) // 注销主服务
}
